package com.jiawei.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.jiawei.entity.database.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author : willian fu
 * @date : 2019/12/11
 */
@Component
public class JwtUtil {

    @Value("${customize.expires}")
    private Long expires;

    @Value("${customize.key}")
    private String key;

    @Value("${customize.token}")
    private String header;

    private static JWTVerifier jwtVerifier;
    /**
     * 创建token令牌
     * @param user 待加密的用户信息
     * @return jwt token
     */
    public String jwtGetToken(User user) {
        String token= JWT.create()
                .withAudience(String.valueOf(user.getId()), user.getUsername())
                .withExpiresAt(new Date(System.currentTimeMillis() + expires * 1000))
                .sign(Algorithm.HMAC256(key));
        return token;
    }

    /**
     * 刷新token
     * @return
     */
    public String jwtRefreshToken() {
        User user = this.jwtGetUser();
        if (user != null) {
            return this.jwtGetToken(user);
        }
        return null;
    }

    /**
     * jwt token校验
     * @param token token字符串
     * @return 校验是否成功
     */
    public boolean jwtVerify(String token){
        JWTVerifier jwtVerifier = this.getJwtVerifier();
        try {
            jwtVerifier.verify(token);
            return true;
        } catch (JWTVerificationException e) {
            return false;
        }
    }

    /**
     * 从jwt token解析用户信息
     * @param token token字符串
     * @return 用户信息实体
     */
    public User jwtGetUserByToken(String token){
        JWTVerifier jwtVerifier = this.getJwtVerifier();
        try {
            List<String> audience = jwtVerifier.verify(token).getAudience();
            if (audience.size() > 1){
                return User.builder().id(Long.valueOf(audience.get(0))).username(audience.get(1)).build();
            }
        } catch (JWTVerificationException e) {
            return null;
        }
        return null;
    }

    /**
     * 从jwt token解析用户信息
     * @return 用户信息实体
     */
    public User jwtGetUser(){
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        return this.jwtGetUserByToken(request.getHeader(header));
    }

    /**
     * 获取token剩余时间
     * @param token
     * @return 剩余时长s
     */
    public Long getTokenExpires(String token){
        JWTVerifier jwtVerifier = this.getJwtVerifier();
        try {
            return jwtVerifier.verify(token).getExpiresAt().getTime() - System.currentTimeMillis();
        } catch (Exception e) {
           return 0L;
        }
    }

    /**
     * 获取 JWTVerifier
     * @return
     */
    public JWTVerifier getJwtVerifier(){
        if (jwtVerifier == null){
            synchronized (JWTVerifier.class) {
                if (jwtVerifier == null) {
                    jwtVerifier = JWT.require(Algorithm.HMAC256(key)).build();
                }
            }
        }
        return jwtVerifier;
    }
}
